#include "ExchangeInterOp.h"
// #include "SPAIopAcisSystem.h"
#include "ExchangeObject.h"
#include "ExchangeDocumentInstance.h"
#include "ExchangeDocumentReference.h"
#include "ExchangeMatrix.h"
#include "ExchangeTopoShape.h"
#include "common/system_log.h"

#ifdef INTEROP_ENABLE
#include "InterOpIO.h"
#include "InterOpDocumentInstance.h"
#include "InterOpDocumentReference.h"
#include "InterOpMatrix.h"
#endif
#include <memory>
#include "ExchangeTopoShape.h"

AMCAX_EXCHANGE_NAMESPACE_BEGIN

namespace
{
    #ifdef INTEROP_ENABLE
    void ConvertDocumentInstanceMiscData(const std::shared_ptr<InterOp::InterOpDocumentInstance> &interOpDocInst, std::shared_ptr<ExchangeDocumentInstance> &exchangeDocInst)
    {
        if(!interOpDocInst){
            LOG_ERROR("InterOpDocumentInstance is nullptr") ;
            return ;
        }
        exchangeDocInst->SetName(interOpDocInst->GetName());
        exchangeDocInst->SetPersistName(interOpDocInst->GetPersistName());
        auto transform = interOpDocInst->GetTransform();
        auto interOpOrientation = transform.GetOrientation();
        double orientation[3][3] = {
            {interOpOrientation[0][0], interOpOrientation[0][1], interOpOrientation[0][2]},
            {interOpOrientation[1][0], interOpOrientation[1][1], interOpOrientation[1][2]},
            {interOpOrientation[2][0], interOpOrientation[2][1], interOpOrientation[2][2]}
        };
        auto interOpOrigin = transform.GetOrigin();
        double origin[3] = {interOpOrigin[0], interOpOrigin[1], interOpOrigin[2]};
        exchangeDocInst->SetTransform(ExchangeMatrix(orientation, origin));
    }
    void ConvertDocumentReferenceMiscData(const std::shared_ptr<InterOp::InterOpDocumentReference> &interOpDocRef, std::shared_ptr<ExchangeDocumentReference> &exchangeDocRef)
    {
        exchangeDocRef->SetId(interOpDocRef->GetId());
        exchangeDocRef->SetName(interOpDocRef->GetName());
        bool isPart = interOpDocRef->IsPart();
        exchangeDocRef->SetIsPart(interOpDocRef->IsPart());
        if(isPart)
        {
            AMCAX::TopoCompound topoCompound;
            interOpDocRef->GetPartShape(topoCompound);
            auto topoShape = std::make_shared<ExchangeTopoShape>(topoCompound) ;
            exchangeDocRef->SetPartShape(topoShape);
        }
    }    
    
    #endif    
}

namespace InterOp {

// SPAIopAcisSystemInitGuard *initGuard;

ExchangeInterOp::ExchangeInterOp(std::string file_path) 
: ExchangeBase(file_path) {
    
};

void ExchangeInterOp::ReadFromFileStream()
{
}

void ExchangeInterOp::Write(const std::vector<ExchangeObjectPtr> &exchange_shapes, const std::shared_ptr<ExchangeDocumentInstance> &exchangeDocumentInstance)
{
    // NOTE: 先拉平，拉平原因是，针对拓扑而言每个Entity，对应一个shape
    std::vector<std::shared_ptr<ExchangeObject>> flatShapes;
    NestedExchangeShapeToFlat(flatShapes, flatShapes);    

    // InterOp::IO::GetInstance().WriterToFile(filePath_,exchange_shapes) ;
}

#ifdef INTEROP_ENABLE
std::shared_ptr<ExchangeObject>  ExchangeInterOp::RecursionConvert(const std::shared_ptr<InterOpObject> &interOpObject)
{
    auto exchangeObject = std::make_shared<ExchangeObject>(interOpObject->id) ;
    exchangeObject->shape =std::make_shared<ExchangeTopoShape>(interOpObject->shape) ;
    // TODO: Add additional properties
    for (auto interOpChild : interOpObject->childs) {
        auto exchangeChild = RecursionConvert(interOpChild) ;
        exchangeObject->AddChild(exchangeChild) ;
    }
    return exchangeObject ;
}

std::shared_ptr<ExchangeDocumentInstance> ExchangeInterOp::ConvertDocumentInstance(const std::shared_ptr<InterOpDocumentInstance> &interOpDocInst)
{
    if(!interOpDocInst){
        LOG_ERROR("InterOpDocumentInstance is nullptr") ;
        return nullptr;
    }
    std::shared_ptr<ExchangeDocumentInstance> docInstance = std::make_shared<ExchangeDocumentInstance>();
    ConvertDocumentInstanceMiscData(interOpDocInst, docInstance);
    auto interOpDocRef = interOpDocInst->GetDocumentReference();
    if(!interOpDocRef)
    {
        return docInstance;
    }
    auto exchangeDocRef = std::make_shared<ExchangeDocumentReference>();
    ConvertDocumentReferenceMiscData(interOpDocRef, exchangeDocRef);
    for(auto& interOpChildDocInstance : interOpDocRef->GetDirectChildInstances())
    {
        auto exchangeChildInst = ConvertDocumentInstance(interOpChildDocInstance);
        exchangeDocRef->AddChildInstance(exchangeChildInst);
    }
    docInstance->SetDocumentReference(exchangeDocRef);

    return docInstance;
}

#endif

void ExchangeInterOp::ReadFromFilePath()
{
#ifdef INTEROP_ENABLE
    if(CheckLicense())
    {
        LOG_INFO("InterOp license check success") ;
    }
    else
    {
        LOG_ERROR("InterOp license check failed") ;
        return ;
    }
    
    std::vector<std::shared_ptr<InterOpObject>> interOpObjectList ;
    std::shared_ptr<InterOpDocumentInstance> interOpDocInst = std::make_shared<InterOpDocumentInstance>();
    InterOp::IO::GetInstance().ReadFromFilePath(filePath_, &interOpObjectList, &interOpDocInst);
    exchangeDocumentRootInstance_ = ConvertDocumentInstance(interOpDocInst);
    
    // TODO: 转换，是否需要递归？
    for (auto &shape : interOpObjectList) {
        auto exchangeObject = RecursionConvert(shape) ;
        exchangeObjectList_.push_back(exchangeObject) ;
    }
#endif
}

bool ExchangeInterOp::CheckLicense(){
#ifdef INTEROP_ENABLE
    std::string license_25_1("") ;

    return AMCAX::Exchange::InterOp::IO::GetInstance().CheckLicense(license_25_1) ;
#endif
    return false ;
}   



}

AMCAX_EXCHANGE_NAMESPACE_END